from rest_framework import serializers
from goods.models import SKU
from .models import OrderInfo, OrderGoods
from datetime import datetime
from django_redis import get_redis_connection
from django.db import transaction


class SKUSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField()

    class Meta:
        model = SKU
        fields = ['id', 'name', 'price', 'default_image_url', 'count']


class SettlementSerializer(serializers.Serializer):
    freight = serializers.DecimalField(max_digits=4, decimal_places=2)
    skus = SKUSerializer(many=True)


class OrderCreateSerializer(serializers.Serializer):
    # 接收的数据
    address = serializers.IntegerField(write_only=True)
    pay_method = serializers.IntegerField(write_only=True)
    # 响应的数据
    order_id = serializers.CharField(read_only=True)

    def validate(self, attrs):
        # 验证收货地址：当前用户的，并且此地址存在
        address_id = attrs['address']
        user = self.context['request'].user
        if user.addresses.filter(pk=address_id).count() <= 0:
            raise serializers.ValidationError('收货地址无效')

        # 验证支付方式
        pay_method = attrs['pay_method']
        if pay_method not in [1, 2]:
            raise serializers.ValidationError('支付方式无效')

        return attrs

    def create(self, validated_data):
        # 1.获取数据：用户，收货地址，支付方式
        user = self.context['request'].user
        address_id = validated_data.get('address')
        pay_method = validated_data.get('pay_method')

        # 3.从redis中读取购物车数据：选中的商品编号、数量
        redis_cli = get_redis_connection('cart')
        sku_ids = redis_cli.smembers('cart_selected%d' % user.id)
        sku_ids = [int(sku_id) for sku_id in sku_ids]
        sku_dict = redis_cli.hgetall('cart%d' % user.id)
        sku_dict = {int(sku_id): int(count) for sku_id, count in sku_dict.items()}

        with transaction.atomic():  # 如下代码可以使用事务
            point = transaction.savepoint()  # 开启事务
            # 2.创建OrderInfo对象
            # 如果支付方式为货到付款则待发货，如果支付方式为支付宝则待支付
            if pay_method == 1:  # 货到付款
                status = 2
            elif pay_method == 2:  # 支付宝
                status = 1
            else:
                status = 1
            order = OrderInfo.objects.create(
                order_id=datetime.now().strftime('%Y%m%d%H%M%S') + '%09d' % user.id,
                user_id=user.id,
                address_id=address_id,
                total_count=0,
                total_amount=0,
                freight=10,  # 在实际开发中，可以调用合作快递公司的接口
                pay_method=pay_method,
                status=status
            )

            # 4.查询商品对象
            skus = SKU.objects.filter(pk__in=sku_ids)

            # 5.遍历
            total_count = 0
            total_amount = 0
            for sku in skus:
                count = sku_dict[sku.id]
                # 5.1判断库存
                if sku.stock < count:
                    # 5.2如果库存不足则抛异常
                    transaction.savepoint_rollback(point)  # 回滚事务
                    raise serializers.ValidationError('商品[%d]库存不足' % sku.id)
                # 5.3如果库存足够则
                # 5.4创建OrderGoods对象
                order_goods = OrderGoods.objects.create(
                    # order_id=order.order_id,
                    order=order,
                    sku=sku,
                    count=count,
                    price=sku.price
                )
                # 5.5修改商品的库存，销量
                sku.stock -= count
                sku.sales += count
                sku.save()
                # 5.6计算总金额、总数量
                total_count += count
                total_amount += sku.price * count

            # 6.修改OrderInfo对象的总金额、总数量属性
            order.total_count = total_count
            order.total_amount = total_amount
            order.save()

            transaction.savepoint_commit(point)

        # 7.删除redis中选中的购物车数据：hash，set
        redis_cli.delete('cart_selected%d' % user.id)
        redis_cli.hdel('cart%d' % user.id, *sku_ids)

        # 8.返回OrderInfo对象
        return order
